import os
import logging
from datetime import datetime, timedelta
from typing import List, Optional
from fastapi import FastAPI, Depends, HTTPException, Query
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
from sqlmodel import Session, select, func, and_
from .db import get_session, create_db_and_tables, check_database_connection
from .models import Rate, RateResponse, LatestRatesResponse, HealthResponse
from .logger import setup_logger
from .scheduler import RateScheduler

# 设置日志
logger = setup_logger()

# 创建FastAPI应用
app = FastAPI(
    title="JPY汇率检测系统",
    description="日元汇率监控与告警系统",
    version="1.0.0"
)

# CORS配置
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # 生产环境应该限制具体域名
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 全局调度器实例
scheduler = None


@app.on_event("startup")
async def startup_event():
    """应用启动事件"""
    global scheduler
    
    logger.info("JPY汇率检测系统启动中...")
    
    # 创建数据库表
    create_db_and_tables()
    
    # 初始化调度器
    scheduler = RateScheduler()
    await scheduler.initialize()
    scheduler.start_scheduler()
    
    logger.info("JPY汇率检测系统启动完成")


@app.on_event("shutdown")
async def shutdown_event():
    """应用关闭事件"""
    global scheduler
    
    logger.info("JPY汇率检测系统关闭中...")
    
    if scheduler:
        scheduler.stop_scheduler()
    
    logger.info("JPY汇率检测系统已关闭")


@app.get("/", response_class=FileResponse)
async def serve_frontend():
    """提供前端页面"""
    return FileResponse("frontend/dist/index.html")


# API路由
@app.get("/api/health", response_model=HealthResponse)
async def health_check():
    """健康检查"""
    db_connected = check_database_connection()
    
    return HealthResponse(
        status="healthy" if db_connected else "unhealthy",
        timestamp=datetime.now(),
        database_connected=db_connected
    )


@app.get("/api/last", response_model=LatestRatesResponse)
async def get_latest_rates(session: Session = Depends(get_session)):
    """获取最新汇率"""
    try:
        # 获取最新的CNY和USD汇率
        cny_stmt = select(Rate).where(Rate.quote == "CNY").order_by(Rate.ts_utc.desc()).limit(1)
        usd_stmt = select(Rate).where(Rate.quote == "USD").order_by(Rate.ts_utc.desc()).limit(1)
        
        cny_rate = session.exec(cny_stmt).first()
        usd_rate = session.exec(usd_stmt).first()
        
        if not cny_rate or not usd_rate:
            raise HTTPException(status_code=404, detail="未找到最新汇率数据")
        
        # 构建响应
        jpy_cny = RateResponse(
            ts_utc=cny_rate.ts_utc,
            base=cny_rate.base,
            quote=cny_rate.quote,
            rate=cny_rate.rate,
            amount_1000=cny_rate.rate * 1000
        )
        
        jpy_usd = RateResponse(
            ts_utc=usd_rate.ts_utc,
            base=usd_rate.base,
            quote=usd_rate.quote,
            rate=usd_rate.rate,
            amount_1000=usd_rate.rate * 1000
        )
        
        return LatestRatesResponse(
            jpy_cny=jpy_cny,
            jpy_usd=jpy_usd,
            last_updated=max(cny_rate.ts_utc, usd_rate.ts_utc)
        )
        
    except Exception as e:
        logger.error(f"获取最新汇率失败: {e}")
        raise HTTPException(status_code=500, detail=str(e))


@app.get("/api/rates", response_model=List[RateResponse])
async def get_rates(
    quote: str = Query(..., description="货币对，如CNY或USD"),
    start: Optional[str] = Query(None, description="开始时间，ISO格式"),
    end: Optional[str] = Query(None, description="结束时间，ISO格式"),
    interval: str = Query("30m", description="时间间隔，30m或1d"),
    session: Session = Depends(get_session)
):
    """获取汇率时间序列"""
    try:
        # 构建查询条件
        conditions = [Rate.quote == quote]
        
        if start:
            start_dt = datetime.fromisoformat(start.replace('Z', '+00:00'))
            conditions.append(Rate.ts_utc >= start_dt)
        
        if end:
            end_dt = datetime.fromisoformat(end.replace('Z', '+00:00'))
            conditions.append(Rate.ts_utc <= end_dt)
        
        # 如果没有指定时间范围，默认返回最近30天
        if not start and not end:
            end_dt = datetime.now()
            start_dt = end_dt - timedelta(days=30)
            conditions.append(Rate.ts_utc >= start_dt)
            conditions.append(Rate.ts_utc <= end_dt)
        
        # 执行查询
        stmt = select(Rate).where(and_(*conditions)).order_by(Rate.ts_utc)
        rates = session.exec(stmt).all()
        
        # 根据间隔过滤数据
        if interval == "1d":
            # 每天只取一条数据（最新的）
            daily_rates = {}
            for rate in rates:
                date_key = rate.ts_utc.date()
                if date_key not in daily_rates or rate.ts_utc > daily_rates[date_key].ts_utc:
                    daily_rates[date_key] = rate
            rates = list(daily_rates.values())
        
        # 构建响应
        result = []
        for rate in rates:
            result.append(RateResponse(
                ts_utc=rate.ts_utc,
                base=rate.base,
                quote=rate.quote,
                rate=rate.rate,
                amount_1000=rate.rate * 1000
            ))
        
        return result
        
    except Exception as e:
        logger.error(f"获取汇率数据失败: {e}")
        raise HTTPException(status_code=500, detail=str(e))


@app.post("/api/trigger-eval")
async def trigger_evaluation():
    """手动触发策略评估"""
    global scheduler
    
    try:
        if not scheduler:
            raise HTTPException(status_code=500, detail="调度器未初始化")
        
        await scheduler.manual_trigger_eval()
        return {"message": "策略评估已触发"}
        
    except Exception as e:
        logger.error(f"手动触发策略评估失败: {e}")
        raise HTTPException(status_code=500, detail=str(e))


@app.post("/api/trigger-fetch")
async def trigger_fetch():
    """手动触发数据拉取"""
    global scheduler
    
    try:
        if not scheduler:
            raise HTTPException(status_code=500, detail="调度器未初始化")
        
        await scheduler.manual_trigger_fetch()
        return {"message": "数据拉取已触发"}
        
    except Exception as e:
        logger.error(f"手动触发数据拉取失败: {e}")
        raise HTTPException(status_code=500, detail=str(e))


# 静态文件服务（前端构建后的文件）
if os.path.exists("frontend/dist"):
    app.mount("/assets", StaticFiles(directory="frontend/dist/assets"), name="assets")


if __name__ == "__main__":
    import uvicorn
    
    host = os.getenv("HOST", "0.0.0.0")
    port = int(os.getenv("PORT", 8000))
    
    uvicorn.run(
        "backend.app:app",
        host=host,
        port=port,
        reload=False,  # 生产环境关闭热重载
        workers=1,     # 树莓派单进程
        loop="uvloop", # 使用uvloop提高性能
        http="httptools"  # 使用httptools
    )
